#ifndef FHE_CORE_DATA_H
#define FHE_CORE_DATA_H

#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <string>

namespace fhe
{
  namespace core
  {
    class Data : public boost::noncopyable
    {
    public:
      typedef boost::shared_ptr< Data > Ptr;
      typedef std::vector< Ptr >::const_iterator ChildIterator;
      
      Data();
      ~Data();
      
      enum Type
      {
        UNKNOWN,
        PARENT,
        BOOL,
        INT,
        DOUBLE,
        STRING,
      };
      
      Type getType() const;
      std::string getTypeString() const;
      
      std::string getName() const;
      void setName( const std::string& name );
      
      bool getBool() const;
      void setBool( bool b );
      
      int getInt() const;
      void setInt( int i );
      
      double getDouble() const;
      void setDouble( double d );
      
      std::string getString() const;
      void setString( const std::string& s );
      
      void setValueString( const std::string& s );
      std::string getValueString() const;

      bool hasChild( const std::string& name ) const;
      Ptr getChild( const std::string& name ) const;
      void addChild( const Ptr& child );
      Ptr addChild( const std::string& name );
      ChildIterator childrenBegin() const;
      ChildIterator childrenEnd() const;
      std::vector< Ptr > children() const;
      
      std::string path() const;
      
      Ptr get( const std::string& path, bool create = false ) const;
      
      template <typename T> 
      T get() const;
      
      template <typename T> 
      T get( const std::string& path ) const
      {
        return get( path, false )->get<T>();
      }
      
      template <typename T>
      void set( T t );
      
      template <typename T>
      void set( const std::string& path, T t )
      {
        get( path, true )->set<T>( t );
      }
      
      template <typename T>
      bool is() const;
      
      template <typename T>
      bool is( const std::string& path ) const
      {
        return get( path, false )->is<T>();
      }
      
    private:
      Type type_;
      std::string name_;
      bool b_;
      int i_;
      double d_;
      std::string s_;
      std::vector< Ptr > children_;
      Data* parent_;
    };
  }
}

#endif
